﻿using Inovout.Runtime;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using DotNetOpenAuth.Messaging;
using Newtonsoft.Json.Linq;

namespace Inovout.Web.Security
{
    public class QQOAuthClient : BaseOAuth2Client
    {
        private const string QQAuthorizationEndpoint = "https://graph.qq.com/oauth2.0/authorize";
        private const string QQTokenEndpoint = "https://graph.qq.com/oauth2.0/token";
        private const string QQOpenIDEndpoint = "https://graph.qq.com/oauth2.0/me";
        private const string QQUserDataServiceEndpoint = "https://graph.qq.com/user/get_user_info";

        public static readonly string OAuth2ClientProviderName = "qq";
        public static readonly Dictionary<string, string> userDataMapping = new Dictionary<string, string>{
            {"username", "nickname"},{"userloginimg", "figureurl"}
        };

        public QQOAuthClient(string providerName)
            : this(providerName, ComponentRegistry.Resolve<IApplication>().Settings["QQClientId"].ToString(),
            ComponentRegistry.Resolve<IApplication>().Settings["QQClientSecret"].ToString(),
            userDataMapping,
            QQAuthorizationEndpoint,
            QQTokenEndpoint,
            QQUserDataServiceEndpoint)
        {
        }
        public QQOAuthClient()
            : this(OAuth2ClientProviderName,
            ComponentRegistry.Resolve<IApplication>().Settings["QQClientId"].ToString(),
            ComponentRegistry.Resolve<IApplication>().Settings["QQClientSecret"].ToString(),
            userDataMapping,
            QQAuthorizationEndpoint,
            QQTokenEndpoint,
            QQUserDataServiceEndpoint)
        {

        }

        public QQOAuthClient(string providerName, string clientId, string clientSecret, Dictionary<string, string> userDataMapping,
            string authorizeEndpoint, string tokenServiceEndpoint, string userDataServiceEndpoint, string scope = null)
            : base(providerName, clientId, clientSecret, userDataMapping,
            authorizeEndpoint, tokenServiceEndpoint, userDataServiceEndpoint, false, scope)
        {

        }

        protected override IDictionary<string, string> GetUserData(string accessToken)
        {
            GetAccessTokenInfo(accessToken).ExtraData.Add("openid", QueryUserOpenID(accessToken));
            var dictory = base.GetUserData(accessToken);
            dictory.Add("id", QueryUserOpenID(accessToken));
            return dictory;
        }

        protected override void AppendUserDataQuery(UriBuilder builder, AccessTokenInfo accessTokenInfo)
        {
            builder.AppendQueryArgument("openid", accessTokenInfo.ExtraData["openid"].ToString());
            builder.AppendQueryArgument("oauth_consumer_key", ComponentRegistry.Resolve<IApplication>().Settings["QQClientId"].ToString());
            builder.AppendQueryArgument("format", "json ");
        }

        protected string QueryUserOpenID(string accessToken)
        {
            HttpClient httpClient = new HttpClient();
            var builder = new UriBuilder(QQOpenIDEndpoint);
            builder.AppendQueryArgument("access_token", accessToken);
            var result = httpClient.GetAsync(builder.Uri);
            var openIdString = result.Result.Content.ReadAsStringAsync().Result;
            string str = (openIdString.Replace("callback( ", "")).Replace(" );\n", "");
            return (JObject.Parse(str))["openid"].ToString();
        }

        protected override Newtonsoft.Json.Linq.JObject ConvertToJObject(string tokenString)
        {
            JObject tokenJson = new JObject();
            foreach (string kv in tokenString.Split('&'))
            {
                var kvp = kv.Split('=');
                tokenJson.Add(kvp[0], kvp[1]);
            }
            return tokenJson;
        }
    }
}
